	.section .rodata
	.align 2
filename:
	.string "mandelbrot.pgm"
errmsg:
	.string "Error opening output file\n"
	.equ errmsglen, 26
	.equ O_WRONLY, 0001
	.equ O_RDWR,   0002
	.equ O_CREAT,  0100
	.equ O_TRUNC, 01000
	.equ flag, O_WRONLY|O_CREAT|O_TRUNC
	.equ S_IRWXU, 0600
	.equ S_IRWXG, 060
	.equ S_IRWXO, 06
	.equ mode, S_IRWXU|S_IRWXG|S_IRWXO
hdr1:
	.string "P2\n"
	.equ hdr1len, 3
hdr2:
	.string "400 400\n"
	.equ hdr2len, 8
hdr3:
	.string "255\n"
	.equ hdr3len, 4
	.equ IMG_WIDTH, 400
	.equ IMG_HEIGHT, 400
	.equ SCALEPARAM, 10 @ scale=1024
	.equ RE_MIN, 0xfffffa00 @ -1.5 *1024
	.equ RE_MAX, 0x4cc @ 1.2 * 1024
	.equ IM_MIN, 0
	.equ IM_MAX, 0x600 @ 1.5 * 1024
	.equ WFACT, (RE_MAX - RE_MIN)/(IMG_WIDTH-1)
	.equ HFACT, (IM_MAX - IM_MIN)/(IMG_HEIGHT-1)
fmt:
	.string "%3d "
endl:
	.string "\n"

	.text
	.align 2
	.global main

main:
	@ Open file (syscall 5)
	ldr r0, =filename
	ldr r1, =flag
	ldr r2, =mode
	mov r7, #5
	swi 0

	@ Test returned FD, display message in case of error
	cmp r0, #0
	@ write to stderr
	movle r0, #2
	ldrle r1, =errmsg
	movle r2, #errmsglen
	movle r7, #4
	swile 0
	@ exit
	movle r0, #1
	movle r7, #1
	swile 0

	@ Write image header (syscall 4)
	@r0 holds FD, back it up in a register
	mov r4, r0
	ldr r1, =hdr1
	mov r2, #hdr1len
	mov r7, #4
	swi 0
	mov r0, r4
	ldr r1, =hdr2
	mov r2, #hdr2len
	swi 0
	mov r0, r4
	ldr r1, =hdr3
	mov r2, #hdr3len
	swi 0

	@ Compute Mandelbrot set
	mov r0, r4
	bl draw_picture
	
	@ Close file (syscall 6)
	@ r4 holds FD
	mov r0, r4
	mov r7, #6
	swi 0

	@ Exit (syscall 1)
	mov r0, #0
	mov r7, #1
	swi 0

draw_picture:
	@ Save return adress
	stmfd sp!, {r4-r10, lr}
	@ r0 holds FD, back it up in a register
	mov r10, r0
	@ Allocated a buffer on stack for formatted output conversion
	sub sp, sp, #8

	@ Height loop
	ldr r4, =IMG_HEIGHT
looph:	subs r4, r4, #1 @ Step outer loop
	blt out_draw @ Do it until iterator becomes negative
	@ Width loop
	mov r5, #0
	ldr r6, =IMG_WIDTH
loopw:	cmp r5, r6
	bge out_draw_inner

	@ Compute Real part of c
	ldr r7, =WFACT
	mul r0, r5, r7
	ldr r8, =RE_MIN
	add r0, r0, r8
	@ Compute Imaginary part of c
	ldr r9, =HFACT
	mul r1, r4, r9
	ldr r7, =IM_MIN
	add r1, r1, r7
	
	@ Check convergence speed
	ldr r2, =SCALEPARAM
	bl iteration
	mov r3, r0
	
	@ Print result
	@ convert first number to char*
	mov r0, sp
	mov r1, #8
	ldr r2, =fmt
	bl snprintf
	@ Write string to output file
	mov r0, r10 @ FD
	mov r1, sp
	mov r2, #4
	mov r7, #4
	swi 0
	@ Close inner loop
	add r5, r5, #1 @ Step inner loop
	b loopw
out_draw_inner:
	@ Print end line
	mov r0, r10 @ FD
	ldr r1, =endl
	mov r2, #1
	swi 0
	@ Close outer loop
	b looph

out_draw:
	@ Unallocate buffer
	add sp, sp, #8
	@ Restore return address
	ldmfd sp!, {r4-r10, lr}
	bx lr

iteration:
	/* sauvegarde sur la pile */
	stmfd sp!, {r4-r11, lr}		

initialize:
	/* zRe = 0, zIm = 0, k=0*/
	mov r3, #0
	mov r4, #0
	mov r5, #0
	/* r11 = shift -1 */
	sub r11, r2, #1
	
test1:
	/*  zRe^2 / s  */
	mul r6, r3, r3
	LSR r6, r6, r2

	/*  zIm^2 / s  */
	mul r7, r4, r4
	LSR r7, r7, r2	

	/* zRe^2 / s  +  zIM^2 / s */
	add r8, r6, r7
	
	/* 4 x s */
	mov r9, #4
	LSL r9, r9, r2
	
	/* (zRe*zRe/s + zIm*zIm/s <= 4*s) */
	cmp r8, r9
	bgt end_iter

test2:
	/* k < 255 */
	cmp r5, #255
	bge end_iter

loop:
	/* zReOld = zRe */
	mov r10, r3
	
	/* zRe = zRe*zRe/s - zIm*zIm/s + cRe */
	sub r3, r6, r7
	add r3, r3, r0
	
	/* zIm = 2*zIm*zReOld/s + cIm */
	mul r6, r4, r10
	ASR r4, r6, r11
	add r4, r4, r1
	
	/* k += 1 */
	add r5, #1
	b test1
	
end_iter:
	/* valeur de retour, return k */
	mov r0, r5

	/* restaure la pile */
	ldmfd sp!, {r4-r11, lr}
	bx lr
